/**
 * 
 */
package com.baijia.tianxiao.push.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baijia.tianxiao.push.biz.channel.StandardChannel;
import com.baijia.tianxiao.push.enums.ChannelTypeEnum;
import com.baijia.tianxiao.push.enums.DeviceTypeEnum;
import com.baijia.tianxiao.push.enums.PushCodeEnum;
import com.baijia.tianxiao.push.model.PushBindChannel;
import com.baijia.tianxiao.push.model.PushBindRecord;
import com.baijia.tianxiao.push.model.PushMessage;
import com.baijia.tianxiao.push.result.BasePushResult;
import com.baijia.tianxiao.push.service.PushBindRecordService;
import com.baijia.tianxiao.push.service.PushMessageService;

/**
 * @author leiruiqi
 *
 */
@Service("pushMessageService")
public class PushMessageServiceImpl implements PushMessageService{

	private static Logger logger = LoggerFactory.getLogger(PushMessageServiceImpl.class); 
	
	@Resource
	private PushBindRecordService pushBindRecordService;
	
	
	@Override
	public BasePushResult pushSingle(PushMessage message) {
		
		logger.info("push Signle pushMessage: "+JSON.toJSONString(message));
		String deviceId = message.getDeviceId();
		
		if(StringUtils.isNotBlank(deviceId)){
			return sendByDeviceId(message);		
		}
		
		List<PushBindRecord> recordList = pushBindRecordService.qureyUserBindList(message.getUserId(),message.getBizType(),null);
		if(CollectionUtils.isEmpty(recordList)){
			return new BasePushResult(false, "user not exit");
		}
		/*if(latestRecord.getBindStatus()!=1){
			return new BasePushResult(false, "user unbind");
		}
		
		PushBindChannel defaultChannel = getDefaultPushBindChannel(latestRecord);
		if(defaultChannel == null){
			return new BasePushResult(false, "channel Disable");
		}
		
		StandardChannel channel = StandardChannel.channelMap.get(defaultChannel.getChannelType());
		
		BasePushResult result=  (BasePushResult)channel.sendPushMsg(JSON.parseObject(messagea.getMessageInfo()),defaultChannel.getAppId(), defaultChannel.getDeviceToken(), latestRecord.getDeviceType(), 1);
		
		return result;*/
		BasePushResult result = new BasePushResult();
		
		for(PushBindRecord record:recordList){
			BasePushResult tempresult = sendByChannel(record,message);
			if(tempresult.isSuccess()){
				result.setSuccess(true);
			}else{
				if(StringUtils.isNotBlank(result.getMsg())){
					result.addMsg(result.getMsg());
				}
				
			}
		}
		return result;
		
	}
	
	private BasePushResult sendByDeviceId(PushMessage message){
		BasePushResult pushResult = new BasePushResult();
		List<PushBindRecord> list = pushBindRecordService.queryUserBindListByDeviceId(message.getDeviceId());
		if(CollectionUtils.isNotEmpty(list)){
			PushBindRecord bindRecord = list.get(0);
			if(StringUtils.equals(bindRecord.getUserId(),message.getUserId())&&StringUtils.equals(bindRecord.getUserType(),message.getBizType())){
				BasePushResult tempresult = sendByChannel(bindRecord,message);
				return tempresult;
			}
		}
		
		pushResult.setSuccess(false);
		pushResult.setMsg("device user not exist");
		return pushResult;
	}
	
	private BasePushResult sendByChannel(PushBindRecord record,PushMessage messagea){
		
		if(record.getBindStatus()!=1){
			return new BasePushResult(false, "user unbind");
		}
		
		PushBindChannel defaultChannel = getDefaultPushBindChannel(record);
		if(defaultChannel == null){
			return new BasePushResult(false, "channel Disable");
		}
		
		StandardChannel channel = StandardChannel.channelMap.get(defaultChannel.getChannelType());
		
		Integer deployStatus = defaultChannel.getDeployStatus();
		Integer developStatus = defaultChannel.getDevelopStatus();
		
		if(developStatus == null){
			developStatus = 1;
		}
		if(StringUtils.equals(record.getDeviceType(),DeviceTypeEnum.IOS.name()) &&deployStatus == null){
			deployStatus = 2;
		}
		
		BasePushResult result=  (BasePushResult)channel.sendPushMsg(JSON.parseObject(messagea.getMessageInfo()),defaultChannel.getAppId(), defaultChannel.getDeviceToken(), record.getDeviceType(), developStatus,deployStatus);
		logger.info("send push result userId="+record.getUserId()+", DeviceId="+record.getDeviceId()+",result="+result.isSuccess()+", code="+result.getCode()+",message="+result.getMsg());
		
		if(!result.isSuccess()){
			
			if(StringUtils.equals(result.getCode(), PushCodeEnum.bind_no_found.name())){
				logger.info("unBindDevice for code bind_no_found bindRecord={}",record);
				pushBindRecordService.unBindByDeviceId(record.getDeviceId());
			}
		}
		
		return result;
			
		
	}
	
	 
	
	private PushBindChannel getDefaultPushBindChannel(PushBindRecord pushBindRecord){
		 List<PushBindChannel> channelList = pushBindRecord.getChannelList();
		 if(CollectionUtils.isEmpty(channelList)){
			 return null;
		 }
		 if(channelList.size()==1){
			 return channelList.get(0);
		 }
		 Map<String,PushBindChannel> map = new HashMap<String,PushBindChannel>();
		 for(PushBindChannel channel:channelList){
			 map.put(channel.getChannelType(), channel);
		 }
		 PushBindChannel tempChannel = null;
		 tempChannel = getChannelByType(map,ChannelTypeEnum.HUAWEI);
		 if(tempChannel!=null){
			 return tempChannel;
		 }
		 tempChannel = getChannelByType(map,ChannelTypeEnum.XIAOMI);
		 if(tempChannel!=null){
			 return tempChannel;
		 }
		 tempChannel = getChannelByType(map,ChannelTypeEnum.BAIDU);
		 if(tempChannel!=null){
			 return tempChannel;
		 }
		 return null;
	}
	
	private PushBindChannel getChannelByType(Map<String,PushBindChannel> map,ChannelTypeEnum type){
		String typeName = type.name();
		if(map.containsKey(typeName) && StandardChannel.channelMap.containsKey(typeName)){
			return map.get(typeName);
		}
		return null;
	}

	@Override
	public BasePushResult pushSingleByUserPrefix(PushMessage message) {
		List<PushBindRecord> recordList = pushBindRecordService.qureyUserBindByPrefix(message.getUserId(),message.getBizType(),null);
		if(CollectionUtils.isEmpty(recordList)){
			return new BasePushResult(false, "user not exit");
		}
		
		BasePushResult result = new BasePushResult();
		
		for(PushBindRecord record:recordList){
			BasePushResult tempresult = sendByChannel(record,message);
			if(tempresult.isSuccess()){
				result.setSuccess(true);
			}else{
				if(StringUtils.isNotBlank(result.getMsg())){
					result.addMsg(result.getMsg());
				}
				
			}
		}
		return result;
	}

}
